package demo8;

import lombok.Getter;
import lombok.Setter;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * :simple-demo:test --tests "demo8.CompositionDemo1Test.test4"  --info -Dorg.gradle.jvmargs="-Xmx4g -Xms1g -verbose:gc"
 */
public class CompositionDemo1 {
    public CompositionDemo2 createCompositionDemo2() {
        return new CompositionDemo2();
    }

    public CompositionDemo3 createCompositionDemo3() {
        return new CompositionDemo3();
    }

    public CompositionDemo4 createCompositionDemo4() {
        return new CompositionDemo4();
    }

    Timer timer = new Timer(true);

    @Setter
    @Getter
    public class CompositionDemo4 {
        AtomicInteger counter = new AtomicInteger(0);
        ArrayList<List<Integer>> allCom = null;
        // ele

        public void composition(String[] arr, int start, int end) {
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println("===================================================================current counter is : " + getCounter().get());
                }
            }, 0l,1000 * 60l);
            reComposition(arr,end - 1, start - 1, arr[0]);
//            print(list);

        }

        // 0,1,2,3
        private void reComposition(String[] arr,int end, int start, String str) {
            if (start == end) {
                System.out.println(str);
                counter.incrementAndGet();
                return;
            }

            for (int j = 0; j <= str.length(); j++) {
                // "1","0",0
                String newStr = insertChar(arr[(end + 1)] , str, j);

                reComposition(arr,end - 1, start, newStr);
            }
        }


        private String insertChar(String dest, String source, int j) {
            // 3 , 0-2
            String start = source.substring(0, j);
            String end = source.substring(j);
            return start + dest + end;
        }

        public void print(List<String> composition) {
            for (int i = 0; i < composition.size(); i++) {
                System.out.println(composition.get(i).toString());
            }
        }
    }

    @Setter
    @Getter
    public class CompositionDemo3 {
        int counter = 0;
        ArrayList<List<Integer>> allCom = null;
        List<Integer> composition = new ArrayList<Integer>() {{
            add(0);
        }};

        public void composition(int start, int end) {
            reComposition(end - 1, start - 1, composition);
        }

        // 0,1,2,3
        // [0,1] [1,0]
        // [0,1,2] [0,2,1]
        private void reComposition(int end, int start, List<Integer> compositionList) {
            // 1-> [0]
            // 2-> [0,1] [1,0]
            //
            if (start == end) {
                return;
            }
            int size2 = compositionList.size();
            for (int i = 0; i <= size2; i++) {
                // 2,0,1
                // 1,0,2
                ArrayList<Integer> integers = new ArrayList<>(compositionList);
                integers.add(i, end + 1);
                if (end == 0) {
                    counter++;
                    System.out.println(integers.toString());
                    integers = null;
                }
                reComposition(end - 1, start, integers);
                integers = null;
            }

        }

        public void print(List<List<Integer>> composition) {
            for (int i = 0; i < composition.size(); i++) {
                System.out.println(composition.get(i).toString());
            }
        }
    }

    /**
     * 内存使用过多，不适合， 无需保存，
     */
    @Setter
    @Getter
    public class CompositionDemo2 {
        ArrayList<List<Integer>> allCom = null;

        public List<List<Integer>> composition(int start, int end) {
            List<List<Integer>> composition = reComposition(end, start);
            return composition;
        }

        List<List<Integer>> composition = new ArrayList<List<Integer>>() {{
            add(new ArrayList<Integer>() {{
                add(0);
            }});
        }};

        private List<List<Integer>> reComposition(int end, int start) {
// -1 ~ 5                                               8       5
            if (start == end) {
                return composition;
            }
            // f(8,5) f(7,5) f(6,5) f(5,5)
            // 9,8,7
            List<List<Integer>> lists1 = reComposition(end - 1, start);
            int size2 = lists1.size();
            // todo update the gatter method,  try to print ,don't store
            for (int j = 0; j < size2; j++) {
                List<Integer> lists = lists1.get(j);
                int size = lists.size();
                ArrayList<Integer> integers = null;
                for (int i = 0; i < size; i++) {
                    // 1,2,3,4,5,6,7,8
                    integers = new ArrayList<>(lists);
                    integers.add(i, end + 1);
                    composition.add(integers);
                }
                integers = new ArrayList<>(lists);
                integers.add(end + 1);
                composition.add(integers);
            }
            for (int i = 1; i <= size2; i++) {
                composition.remove(0);
            }
            return composition;

        }

        public void print(List<List<Integer>> composition) {
            for (int i = 0; i < composition.size(); i++) {
                System.out.println(composition.get(i).toString());
            }
        }
    }


    /**
     * 列出 字符串的所有排列组合， 注意：字符串不重复，
     * <p>
     * use the iterator method ,.need to use for loop  is n times;
     * no, 需要顺序，而且组合不能重复， 应该是 n! ,可以尝试采用递归
     * 0,1 2 =>
     * 2 -> 0,1
     * 2 针对集合的插入方式
     * <p>
     * 1 -> 0,
     * <p>
     * 1,0, 0,1
     * <p>
     * List<List<>>
     * [[2,0,1],[0,1,2]]
     */
    ArrayList<List<Integer>> allCom = null;

    // 0->1  length =1 , start =0 ,
    // composition(0,3)
    public List<List<Integer>> composition(int start, int end) {
// iterator length times;
        if (end == start) {
            // one ele.
            allCom = new ArrayList<List<Integer>>() {{
                add(new ArrayList<Integer>() {{
                    add(0);
                }});
            }};
        } else {
            List<List<Integer>> composition = composition(start, end - 1);
            int size = composition.size();
            ArrayList<Integer> integers = new ArrayList<>();
            reComposition(size, 0, end, composition);
            for (int i = 0; i < size; i++) {
                composition.remove(0);
            }

        }
        return allCom;

    }

    private void reComposition(int length, int pos, int val, List<List<Integer>> composition) {
        List<Integer> lists = composition.get(pos);

        if (length == pos) {
            return;
        }

        int size = lists.size();
        ArrayList<Integer> integers = null;
        for (int i = 0; i < size; i++) {
            integers = new ArrayList<>(lists);
            integers.add(i, val);
            composition.add(integers);
        }
        integers = new ArrayList<>(lists);
        integers.add(val);
        composition.add(integers);

// [[0,1][1,0]]
// composition get the lastest level,
        reComposition(length, pos + 1, val, composition);

    }

    public void print(List<List<Integer>> composition) {
        for (int i = 0; i < composition.size(); i++) {
            System.out.println(composition.get(i).toString());
        }
    }
}
